home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / ada / adaed-1.11 / adaed-1 / Adaed-1.11.0a / errs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-07  |  11.1 KB  |  379 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. #include "ada.h"
  10. #include "ifile.h"
  11. #include "libfprots.h"
  12. #include "pspansprots.h"
  13. #include "adalexprots.h"
  14. #include "errsprots.h"
  15.  
  16. extern IFILE *astfile;            /* File pointer for ast file */
  17.  
  18. static void printerr(struct tok_loc *, struct tok_loc *, char *);
  19. static void err_display(char *);
  20. static void write_error(int, char *, struct tok_loc *, struct tok_loc *);
  21. static void print_tuple(struct ast *);
  22.  
  23. /* This file contains functions for printing error messages.
  24.    To print an error message given the complete message and spans,
  25.    printerr is used. To print a syntax error, syntax_err is
  26.    used.
  27.    It also contains the procedures used to write the astfile.
  28.    A comment at the end of this file describes the format
  29.    of the astfile.
  30.  */
  31.  
  32.  
  33. /* Printerr: print error message to the terminal 
  34.  * this should be called only in case some debugging option is set (-ert)
  35.  * Error message is printed to stdout if termopt set, to errfile if redopt or
  36.  * erropt set 
  37.  * If the error is not on the most recently printed source line, print the line
  38.  * (or last line if it spans multiple lines) first, followed by an underlining
  39.  * or pointer to error location.
  40.  */
  41.  
  42.  
  43. static void printerr(struct tok_loc *lspan, struct tok_loc *rspan, char *msg)
  44.                                                             /*;printerr*/
  45. {
  46.     int i;
  47.     char tmp_str[150];
  48.  
  49.     if (lspan->line==rspan->line || lineno - rspan->line < NUM_LINES)
  50.     {
  51.         /* print source line (or last line ) */
  52.         if (rspan->line != lineno   &&  /* error at current line */
  53.         !(feof(adafile) && lspan->line==lineno-1 &&colno==1) ) {
  54.             /* error is at last line in source */
  55.             sprintf(tmp_str, "%5d:  %s\n", rspan->line, source_buf[
  56.               (src_index + NUM_LINES - (lineno - rspan->line)) % NUM_LINES]);
  57.             err_display(tmp_str);
  58.         }
  59.         /* underline */
  60.         if (lspan->line != rspan->line) {
  61.             err_display(". . . . ");
  62.             for (i = rspan->col; --i;)
  63.                 err_display("-");
  64.             err_display(">\n");
  65.         }
  66.         else { /* error spans more than one line */
  67.             for (i = lspan->col + 8; --i;)
  68.                 err_display(" ");
  69.             if (rspan->col - lspan->col <= 1)
  70.                 err_display("^");
  71.             else {
  72.                 err_display("<");
  73.                 for (i = rspan->col - lspan->col - 1; i--;)
  74.                     err_display("-");
  75.                 err_display(">");
  76.             }
  77.             err_display("\n");
  78.         }
  79.     }
  80.     else {
  81.         sprintf(tmp_str, "-- Between line %d column %d and line %d column %d\n",
  82.           lspan->line, lspan->col, rspan->line, rspan->col);
  83.         err_display(tmp_str);
  84.     }
  85.     err_display(msg);
  86.     err_display("\n\n");
  87. }
  88.  
  89. static void err_display(char *str)                            /*;err_display*/
  90. {
  91.     if (termopt)
  92.         printf("%s", str);
  93. #ifdef DEBUG
  94.     if (trcopt)
  95.         fprintf(errfile, "%s", str);
  96. #endif
  97. }
  98.  
  99.  
  100. /* Syntax_err: Report an error detected during parsing actions */
  101.  
  102. void syntax_err(struct tok_loc *lspan, struct tok_loc *rspan, char *msg)
  103.                                                             /*;syntax_err*/
  104. {
  105.     char newmsg[300];
  106.  
  107.     err_ct++;
  108.     write_error(ERR_SYNTAX, msg, lspan, rspan);
  109.     sprintf(newmsg, "*** Syntax error: %s", msg);
  110.     if (debugopt)
  111.         printerr(lspan, rspan, newmsg);
  112. }
  113.  
  114.  
  115. void match_error(int id1, int id2, char *construct, struct tok_loc *lspan,
  116.   struct tok_loc *rspan)                                    /*;match_error*/
  117. {
  118.     /* Match_error: Report an error in matching two identifiers */
  119.     char msg[200];
  120.  
  121.     sprintf(msg, "%s at beginning of %s does not match %s",
  122.       namelist(id1), construct, namelist(id2));
  123.     syntax_err(lspan, rspan, msg);
  124. }
  125.  
  126. void prs_warning(struct tok_loc *lspan, struct tok_loc *rspan,  char *msg)
  127.                                                             /*;prs_warning*/
  128. {
  129.     /* Prs_warning: Report a warning message */
  130.     char newmsg[200];
  131.  
  132.     write_error(ERR_WARNING, msg, lspan, rspan);
  133.     sprintf(newmsg, "*** Warning: %s", msg);
  134.     if (debugopt)
  135.         printerr(lspan, rspan, newmsg);
  136. }
  137.  
  138.  
  139. void lexerr(int line, int col1, int col2, char *msg)            /*;lexerr*/
  140. {
  141.     /* Lexerr: Report an error detected by the lexical scanner */
  142.     char nmsg[300];
  143.     struct tok_loc span1, span2;
  144.  
  145.     err_ct++;
  146.     span1.line = span2.line = line;
  147.     span1.col = col1;
  148.     span2.col = col2;
  149.     write_error(ERR_LEXICAL, msg, &span1, &span2);
  150.     sprintf(nmsg, "*** Lexical Error: %s", msg);
  151.     if (debugopt)
  152.         printerr(&span1, &span2, nmsg);
  153. }
  154.  
  155. /* This file contains functions dealing with files that need to be
  156.    written so other programs can read them.
  157. */
  158.  
  159.  
  160. /* So that the error messages can be merged with the listing of the
  161.    source file, and so that the pragmas LIST and PAGE are taken into
  162.    consideration properly, msgfile is written with information about
  163.    occurrances of the above. The format is as follows
  164.  
  165.    error_or_pragma_type lspan rspan
  166.    error_mssage
  167.  
  168.    where lspan and rspan are each two integers, error_or_pragma_type
  169.    is the type of error or pragma (defined in msgs.h), and error_message
  170.    is the error message in the case of an error. There is no error
  171.    message for pragmas (though there may be a seperate set of lines
  172.    for an error message which is there because of the pragma
  173. */
  174.  
  175.  
  176. void write_pragma(int pragma_type, struct tok_loc *lspan, struct tok_loc *rspan)
  177.                                                             /*;write_pragma*/
  178. {
  179.     /* Write_pragma: Writes data about pragma LIST and PAGE to the msgfile */
  180.     fprintf(msgfile, "%d %d %d %d %d\n", pragma_type, lspan->line,
  181.       lspan->col, rspan->line, rspan->col);
  182. }
  183.  
  184. static void write_error(int error_type, char *msg, struct tok_loc *lspan,
  185.   struct tok_loc *rspan)                                    /*;write_error*/
  186. {
  187.     /* Write_error: Write data about errors to msgfile */
  188.     fprintf(msgfile, "%d %d %d %d %d\t%s\n", error_type, lspan->line,
  189.       lspan->col, rspan->line, rspan->col, msg);
  190. }
  191.  
  192. /* Routines for printing the AST to a file in SETL format. */
  193.  
  194. static int node_count; /* A count for assigning a small integer to each node. */
  195.  
  196. #define SETLopt_node 0
  197. /* Representation of opt_node in SETL front end */
  198.  
  199.  
  200. /* Print_tree: Print the AST in a file so that the SETL semantic phase
  201.    can use it. The AST is written in the form of a list of SETL tuples,
  202.    each representing a node of the tree. The format is
  203.    [kind, spans, ast, val, list] (note that the spans is a tuple containing
  204.    two tuples of the form [line, col1, col2]). The tree is traversed, and
  205.    the nodes are printed in a bottom up fashion. Each node is assigned
  206.    a node number (which is stored in the spans field after it is printed).
  207.    Because each parent must know the node numbers of its children in order
  208.    to print the ast and list, we process the children of each node before
  209.    the node itself. So the root of the tree ends up being the last tuple
  210.    printed.
  211. */
  212. /* The above was once true, but has been obsolete for quite a while. It
  213.  * has, however, served as a model for the current implementation.
  214.  */
  215.  
  216. void print_tree(struct ast *root)                                /*;print_tree*/
  217. {
  218.     if (root != NULL)
  219.     {
  220.         node_count = 0;
  221.         print_tuple(root);
  222.         putnum(astfile, "root", 0);
  223.     }
  224. }
  225.  
  226. static void print_tuple(struct ast *node)                    /*;print_tuple*/
  227. {
  228.     struct two_pool *listptr;
  229.     int i;
  230.  
  231. #ifdef PDEBUG
  232.     if (trcopt)
  233.         fprintf(errfile, "called with node of kind = %d\n", node->kind);
  234. #endif
  235.     /* Call self recursively on children before printing node's own tuple */
  236.     if (islist_node[node->kind]) {
  237.         if (node->links.list != NULL) {
  238.             listptr = node->links.list;
  239.             do {
  240.                 listptr = listptr->link;
  241.                 print_tuple(listptr->val.node);
  242.             }        while(listptr != node->links.list);
  243.         }
  244.     }
  245.     else if (isast_node[node->kind] || node->kind==AS_OTHERS_CHOICE) {
  246.         /* KLUDGE until can rerun makeinit */
  247.         for (i = 0; i < MAX_AST && (node->links.subast)[i] != NULL; i++)
  248.             if ((node->links.subast)[i] != opt_node)
  249.                 print_tuple((node->links.subast)[i]);
  250.     }
  251.  
  252.  
  253. #ifdef PDEBUG
  254.     if (trcopt)
  255.         fprintf(errfile, "Doing stuff for node %d\n", node_count + 1);
  256. #endif
  257.  
  258.     /* Store the node number in the count field so its parent can access it. */
  259.  
  260.     if (node->count == 0) node->count = ++node_count;
  261.  
  262.     /* Write the count and kind (N_KIND) */
  263.     putnum(astfile, "count", node->count);
  264.     putnum(astfile, "kind", node->kind);
  265.  
  266.     /* Write the spans (SPANS) only for terminal nodes */
  267.     if (is_terminal_node(node->kind)) {
  268.         putnum(astfile, "span-line", node->span.line);
  269.         putnum(astfile, "span-col", node->span.col);
  270.     }
  271.  
  272.     /* Special case here for AS_LINE_NO since we only want the line
  273.    number written out */
  274.  
  275.     if (node->kind == AS_LINE_NO)
  276.         putnum(astfile, "line-no", node->links.val);
  277.     else {
  278.  
  279.         /* Print the (sub)ast (N_AST) */
  280.         if (isast_node[node->kind] || node->kind==AS_OTHERS_CHOICE) {
  281.             /* KLUDGE until can rerun makeinit */
  282.             for (i=0 ; (i < MAX_AST) && ((node->links.subast)[i] != NULL); i++);
  283.             putnum(astfile, "subast", i);
  284.  
  285.             i = 0;
  286.             while (1) {
  287.                 putnum(astfile, "node",
  288.                   ((node->links.subast)[i] != opt_node) ? 
  289.                   ((node->links.subast)[i]->count) : SETLopt_node);
  290.                 if (!(++i < MAX_AST && (node->links.subast)[i] != NULL))
  291.                     break;
  292.             }
  293.         }
  294.         else {
  295.             putnum(astfile, "none", 0);
  296.         }
  297.         /* Print the list (on a new line, max 12 per line)    (N_LIST) */
  298.         if (islist_node[node->kind]) {
  299.  
  300.             if (node->links.list != NULL) {
  301.                 i = 0 ;
  302.                 listptr = node->links.list ;
  303.                 while( 1 ) {
  304.                     i++ ;
  305.                     listptr = listptr->link ;
  306.                     if (listptr == node->links.list)
  307.                         break;
  308.                 }
  309.                 putnum(astfile, "list-size", i);
  310.                 listptr = node->links.list;
  311.                 i = 1;
  312.                 while (1) {
  313.                     listptr = listptr->link;
  314.                     putnum(astfile, "count", listptr->val.node->count);
  315.                     if (listptr == node->links.list)
  316.                         break;
  317.                 }
  318.             }
  319.             else {
  320.                 putnum(astfile, "none", 0);
  321.             }
  322.         }
  323.         else {
  324.             putnum(astfile, "not-list", -1);
  325.         }
  326.         /* Write the val (N_VAL) */
  327.         if (isval_node[node->kind]) {
  328.             putnum(astfile, "is-val", 1); /* indicate a VAL field */
  329.             putstr(astfile, "val", namelist(node->links.val));
  330.         }
  331.         else {
  332.             putnum(astfile, "no-val", 0); /* indicate no VAL field */
  333.         }
  334.     }
  335.  
  336. #ifdef PDEBUG
  337.     if (trcopt)
  338.         fprintf(errfile, "Returning for node %d\n", node_count);
  339. #endif
  340. }
  341.  
  342. /*
  343.  * The format of the asftile is as follows. The file is a text file in
  344.  * the form of a SETL data set. Each entry is a tuple. The end of a 
  345.  * compilation unit is denoted by a null tuple. Each tuple begins
  346.  * with six integers:
  347.  *     kind
  348.  *     line1
  349.  *     col1
  350.  *     line2
  351.  *     col2
  352.  *     astcount
  353.  * If astcount is zero there are no (sub)ast nodes; otherwise there
  354.  * follow astcount integers giving the nodes in the (sub)ast.
  355.  * Next comes the list count. If this is -1 there is no list.
  356.  * If the list count is 0 there is a list but it has no entries.
  357.  * If the list count is positive, it is followed that number of
  358.  * integers giving the node numbers of the items in the list.
  359.  * Last, if the VAL field is defined for this kind of node, there
  360.  * comes the VAL field in the form of a SETL string.
  361.  * 
  362.  * The current format differs from the above in that integer valus
  363.  * are followed by comma characters and there is in some cases a
  364.  * comma after a string literal where a right bracket ']' should occur.
  365.  * 
  366.  * Within each compilation unit, nodes are referenced in the astfile
  367.  * by integers starting with 1. The last (non-null) tuple is the root
  368.  * of the compilation unit.
  369.  * 
  370.  * Binary format.
  371.  * The binary format uses short integers for integer values.
  372.  * The string '[]' in SETL form is represented by (short) integer 0.
  373.  * The VAL field is written as follows:
  374.  *     0    if no VAL
  375.  *     1+n    if VAL field, in which case the count is follows
  376.  *         by the n characters representing the value (no \0)
  377.  *         and end.
  378.  */
  379.